package com.price.httplib.base

import com.price.common.extend.internalCacheDirPath
import com.price.httplib.core.NullOnEmptyConverterFactory
import retrofit2.Retrofit
import okhttp3.Cache
import okhttp3.ConnectionPool
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.converter.gson.GsonConverterFactory
import java.io.File
import java.util.concurrent.TimeUnit

/**
 * 设置服务器配置，比如域名，公共请求头，返回数据格式
 * 网络请求，Retrofit 基础配置 BaseRetrofitConfig
 *
 * https://github.com/AnyLifeZLB
 */
abstract class BaseHttpApiService//全局的错误处理器
{

    // object 与companion object的区别 https://www.jianshu.com/p/14db81e1576a
    companion object {
        private var mRetrofit: Retrofit?=null //C 位主角
    }


    /**
     * 再封装一下，这样还是有点不一样
     *
     * getXXXApiService  就可以调用多方便
     *
     */
    open fun <T> getService(service: Class<T>): T  {
        //Retrofit 的核心操作
        //create方法就是返回了一个Proxy.newProxyInstance动态代理对象
        if(mRetrofit==null){
            initRetrofit()
        }
        return mRetrofit!!.create(service)
    }

    private fun initRetrofit() {
        val baseUrl=getServiceUrl()
        if(baseUrl.isNullOrEmpty()){
            throw RuntimeException("Service Url must not empty or null")
        }
        val retrofitBuilder = Retrofit.Builder()
            .baseUrl(baseUrl)
            .addConverterFactory(NullOnEmptyConverterFactory())
            .addConverterFactory(GsonConverterFactory.create())
//            .addCallAdapterFactory() //全局的错误处理器

        retrofitBuilder.client(getOkHttpClient())
        mRetrofit = retrofitBuilder.build()
    }

    /**
     * OkHttpClient
     */
    private fun getOkHttpClient():OkHttpClient{

        val okHttpClientBuilder = OkHttpClient.Builder()
//            .addInterceptor(CommonRequestInterceptor())

        //返回拦截器
//        okHttpClientBuilder.addInterceptor(CommonResponseInterceptor())
        val interceptors=getInterceptor()
        if(interceptors != null) {
            for(interceptor in interceptors) {
                okHttpClientBuilder.addInterceptor(interceptor)
            }
        }

        //只有在调试状态才需要打印日志
        if(HttpConfig.Debug) {
            val httpLoggingInterceptor = HttpLoggingInterceptor()
            httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
            okHttpClientBuilder.addInterceptor(httpLoggingInterceptor)
        }

        val cacheFile= File(internalCacheDirPath,"HttpCache")
        val cacheSize=10*1024*1024L

        val timeOut=getTimeout()
        val retryOnConnection=retryOnConnection()

        //默认值设置低一点，以便暴露出整个系统的问题所在。
        okHttpClientBuilder
            .retryOnConnectionFailure(retryOnConnection)//默认重试一次，若需要重试N次，则要实现拦截器。
            .cache(Cache(cacheFile,cacheSize))
            .connectTimeout(timeOut,TimeUnit.SECONDS)
            .readTimeout(timeOut,TimeUnit.SECONDS)
            .writeTimeout(timeOut, TimeUnit.SECONDS)
            .callTimeout(timeOut, TimeUnit.MINUTES)
            .connectionPool(ConnectionPool(getMaxIdleConnections(),getKeepAliveDuration(),TimeUnit.MINUTES))


        val  okb=okHttpOtherSet(okHttpClientBuilder)

        return okb.build()
    }


    /**
     * 其他配置
     * */

    protected open fun okHttpOtherSet(okHttpBuilder:OkHttpClient.Builder):OkHttpClient.Builder {
        return okHttpBuilder
    }

    protected open fun getMaxIdleConnections(): Int=20
    protected open fun getKeepAliveDuration(): Long=5

    protected open fun getServiceUrl():String?="http://unkown.com"
    protected open fun getTimeout(): Long=40
    protected open fun retryOnConnection(): Boolean=false

    /**
     * 不同的host 除了通用的拦截器，还可以定制化自己的拦截器
     */
    protected abstract fun getInterceptor(): List<Interceptor>?
}